<template>
  <el-dialog
    :visible.sync="show"
    width="640px"
    title="编辑素材"
    :modal-append-to-body="false"
    :before-close="handleClose"
  >
    <div v-if="!cut.show&&url" style="min-height: 402px;">
      <MaoVideo :url="url" :autoplay="false" style=" width: 100%;height: 402px;border-radius: 15px;overflow: hidden;" />
      <div class="flex-c" style="padding-top: 10px;padding-bottom: 10px;"> 资源加载中，请稍后...</div>
    </div>
    <div v-show="cut.show" v-loading="!cut.show" style="min-height: 402px;">
      <cut-video
        v-if="cut.show"
        ref="cutVideo"
        :url="ff.videoUrl"
        :start-time="cut.startTime"
        :end-time="cut.endTime"
        :spliter-end-time="cut.spliterEndTime"
        :ff-video="ff"
        @sure="onSureCut"
        @cancel="cut.show = false"
        @frame="onVideoFrame"
      />
    </div>
    <span v-if="cut.show" class="flex-e align-center" style="margin-top: 30px">
      <el-button
        type="default"
        size="small"
        @click="handleClose"
      >取消</el-button>
      <el-button type="primary" size="small" @click="cutIt">裁剪</el-button>
    </span>

  </el-dialog>
</template>
<script>
import CutVideo from '@/components/CutVideo/Index.vue'
import checkSize from '@/utils/upload'
import MaoVideo from '@/components/MaoVideo'
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'
const ffmpeg = createFFmpeg({
  corePath: '/ffmpeg-core.js', // 核心文件的路径
  log: false
})
export default {
  name: 'EditVideoModal',
  components: { CutVideo, MaoVideo },
  props: {
    url: {
      type: String,
      default: ''
      // 'https://cesium.com/public/SandcastleSampleData/big-buck-bunny_trailer.mp4'
    },
    item: {
      type: Object,
      default() {
        return {}
      }
    }
  },
  data() {
    return {
      show: false,
      ff: {
        name: '',
        file: null,
        newName: 'newVideo.mp4',
        videoUrl: '',
        newVideoUrl: '',
        blob: null,
        frames: [],
        duration: 0
      },
      cut: {
        spliterEndTime: '00:00:00.0',
        imgs: new Array(10),
        startTime: '00:00:00.0',
        endTime: '00:00:00.00', // // 00:00:1.80
        show: false,
        duration: 0
      }
    }
  },
  methods: {
    cutIt() {
      this.$nextTick(() => {
        if (this.$refs.cutVideo) {
          this.$refs.cutVideo.onSureCut()
          this.handleClose()
        }
      })
    },
    open() {
      this.show = true
      this.dispatchMethods()
    },
    handleClose(done) {
      if (done) {
        done()
      }
      this.show = false
      this.cut.show = false
    },
    urlToBlob(url) {
      return new Promise((resolve) => {
        fetch(url)
          .then(async(response) => {
            const list = response.url.split('/')
            const name = list[list.length - 1]
            return { blob: await response.blob(), name }
          })
          .then((data) => {
            resolve(data)
          })
      })
    },
    blobToFile(theBlob, fileName) {
      theBlob.lastModifiedDate = new Date() // 文件最后的修改日期
      theBlob.name = fileName // 文件名
      return new File([theBlob], fileName, {
        type: theBlob.type,
        lastModified: Date.now()
      })
    },
    parseDuration(duration = 0) {
      console.log('duration', duration)
      const _dur = duration / 10
      const sec = (_dur % 60) * 10
      const min = Math.floor(_dur / 60)
      const hour = min < 60 ? 0 : Math.floor(min / 60)
      // 00:00:1.80
      return `${this.parseNum(hour)}:${this.parseNum(min)}:${sec.toFixed(2).length === 5 ? sec.toFixed(2) : '0' + sec.toFixed(2)}`
    },
    parseNum(num = 0) {
      if (num < 10) {
        return '0' + num
      } else {
        return '' + num
      }
    },
    initVideo() {
      this.urlToBlob(this.url).then(async(data) => {
        const { blob, name } = data
        const file = this.blobToFile(blob, name)

        const { duration } = await checkSize([file])
        // 00:00:1.80
        if (duration) {
          this.$set(this.cut, 'endTime', this.parseDuration(duration))
          console.log(this.cut.endTime)
        }

        const orgFileBuffer = await file.arrayBuffer() // 获取文件数据
        ffmpeg.FS(
          'writeFile',
          file.name,
          await fetchFile(new Blob([orgFileBuffer]))
        ) // 将视频数据写入内存
        const videoUrl = URL.createObjectURL(new Blob([orgFileBuffer])) // 将视频数据转为url

        Object.assign(this.ff, {
          videoUrl,
          name,
          file,
          duration,
          frames: []
        })
        this.$nextTick(() => {
          this.cut.show = true
        })
        return { name, videoUrl }
      })
    },
    async dispatchMethods(methodsName = 'initVideo') {
      if (!ffmpeg.isLoaded()) {
        ffmpeg.load().then(() => {
          this[methodsName]()
        })
      } else {
        this[methodsName]()
      }
    },
    async uploadVideo(e) {
      if (!ffmpeg.isLoaded()) {
        ffmpeg.load().then(async() => {
          const file = e.target.files[0]
          const { name } = file
          const orgFileBuffer = await file.arrayBuffer() // 获取文件数据
          ffmpeg.FS(
            'writeFile',
            name,
            await fetchFile(new Blob([orgFileBuffer]))
          ) // 将视频数据写入内存
          const videoUrl = URL.createObjectURL(new Blob([orgFileBuffer])) // 将视频数据转为url
          const { duration } = await checkSize(e.target.files)

          Object.assign(this.ff, {
            videoUrl,
            name,
            file,
            duration,
            frames: []
          })
          this.$nextTick(() => {
            this.cut.show = true
          })
          return { name, videoUrl }
        })
      } else {
        const file = e.target.files[0]
        const { name } = file
        const orgFileBuffer = await file.arrayBuffer() // 获取文件数据
        ffmpeg.FS(
          'writeFile',
          name,
          await fetchFile(new Blob([orgFileBuffer]))
        ) // 将视频数据写入内存
        const videoUrl = URL.createObjectURL(new Blob([orgFileBuffer])) // 将视频数据转为url
        const { duration } = await checkSize(e.target.files)

        Object.assign(this.ff, {
          videoUrl,
          name,
          file,
          duration,
          frames: []
        })
        this.$nextTick(() => {
          this.cut.show = true
        })
        return { name, videoUrl }
      }
    },
    async onSureCut(e) {
      const startTime = this.time_to_sec(e[0])
      const endTime = this.time_to_sec(e[1])
      // showLoading();
      const { name, newName } = this.ff
      await ffmpeg.run(
        '-ss',
        `${startTime}`,
        '-t',
        `${endTime - startTime}`,
        '-i',
        name,
        '-vcodec',
        'copy',
        '-acodec',
        'copy',
        newName
      )
      const arrayBuffer = ffmpeg.FS('readFile', newName).buffer // 读取缓存
      const blob = new Blob([arrayBuffer])
      this.ff.newVideoUrl = URL.createObjectURL(blob) // 转为Blob URL
      this.ff.blob = blob // 上传文件用
      this.$emit('get', this.ff)
      this.$emit('getTime', this.time_to_sec)
      this.$emit('getTimeRange', [e[0], e[1]])
    },
    onVideoFrame(e) {
      this.ff.frames = e
    },
    time_to_sec(time) {
      const hour = time.split(':')[0]
      const min = time.split(':')[1]
      const sec = time.split(':')[2]
      const s = Number(hour * 3600) + Number(min * 60) + Number(sec)
      return s
    }
  }
}
</script>
